#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/uinput.h>

void emit(int fd, int type, int code, int val)
{
	struct input_event ie;
	
	ie.type = type;
	ie.code = code;
	ie.value = val;
	//以下参数忽略
	ie.time.tv_sec = 0;
	ie.time.tv_usec = 0;
	
	//上报输入事件
	write(fd, &ie, sizeof(ie));
}

int main(int argc, const char *argv[])
{
	int fd;
	struct uinput_setup usetup;
	const char *name = "/dev/uinput";

	if(argc >= 2)
		name = argv[1];

	//打开 uinput 设备
	fd = open(name, O_WRONLY);
	if(fd < 0)
	{
		perror("open");
		return -1;
	}

	//设置属性位图
	if(ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_BUTTONPAD) < 0)
	{
		close(fd);
		perror("UI_SET_PROPBIT");
		return -1;
	}

	//设置事件类型位图和对应的事件码位图
	if(ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
	{
		close(fd);
		perror("UI_SET_EVBIT");
		return -1;
	}
	if(ioctl(fd, UI_SET_KEYBIT, KEY_A) < 0)
	{
		close(fd);
		perror("UI_SET_KEYBIT");
		return -1;
	}

	//设置ID和名称
	memset(&usetup, 0, sizeof(usetup));
	usetup.id.bustype = BUS_USB;
	usetup.id.vendor = 0x1234;
	usetup.id.product = 0x5678;
	strcpy(usetup.name, "Example device");
	if(ioctl(fd, UI_DEV_SETUP, &usetup) < 0)
	{
		close(fd);
		perror("UI_DEV_SETUP");
		return -1;
	}

	//创建输入设备
	if(ioctl(fd, UI_DEV_CREATE) < 0)
	{
		close(fd);
		perror("UI_DEV_CREATE");
		return -1;
	}

	while(1)
	{
		emit(fd, EV_KEY, KEY_A, 1);
		emit(fd, EV_SYN, SYN_REPORT, 0);
		usleep(500*1000);
		emit(fd, EV_KEY, KEY_A, 0);
		emit(fd, EV_SYN, SYN_REPORT, 0);
		usleep(500*1000);
	}

	//close(fd);
}